/**
 * <p>Title: PrivFormula.java</p>
 * <p>Description: </p>
 * <p>Copyright: Baosight Software LTD.co Copyright (c) 2002</p>
 * <p>Company: Baosight Software</p>
 * @author 张志芳
 * @version 1.0
 * <pre>Histroy:
 *          2013-7-22 上午07:37:52  张志芳  Create
 *</pre>
 */
package com.baosight.scaq.common.aq.basetools;

import java.math.BigDecimal;
import java.util.Vector;

/**
 * 公式解析类
 * <p>Title: PrivFormula.java</p>
 * <p>Description: 实现对包含“()”的表达式进行简单的四则运算</p>
 * <p>Copyright: Baosight Software LTD.co Copyright (c) 2002</p>
 * <p>Company: Baosight Software</p>
 * @author 张志芳
 * @version 1.0
 * <pre>Histroy:
 *          2013-7-22 上午07:37:52  张志芳  Create
 *</pre>
 */
public class PrivFormula {

	private int leftBracket = 0; //左括号个数
	private int rightBracket = 0; //右括号个数
	private int startL = 0;
	private int startR = 0;
	private BigDecimal answer = new BigDecimal(0.0);
	@SuppressWarnings("unused")
	private String strValue = "";
	private String leftNumber = "0";
	private String rightNumber = "0";
	public String Msg = "";
	private int msgindex = 0;
	//1 左括弧的个数多于右括弧，请检查！ 2左括弧的个数少于右括弧，请检查！ 3 非法字符 4 公式为空

	private String formula = "";
	private int[] sym = new int[4];
	@SuppressWarnings("rawtypes")
	private Vector list = new Vector();

	public PrivFormula(String calRule) {
		this.setFormula(calRule);
	}

	public PrivFormula() {
		String msgg = "2*1/(111+1)+2*(1-5)";
		this.setFormula(msgg);
	}
	private int getMsgindex() {
		return this.msgindex;
	}

	private int getLeftBracket(String calRule) {
		leftBracket = 0;
		startL = calRule.indexOf("(");
		if (startL != -1) {
			calRule = calRule.substring(startL + 1, calRule.length());
		}
		while (startL != -1) {
			leftBracket++;
			startL = calRule.indexOf("(");
			calRule = calRule.substring(startL + 1, calRule.length());
		}
		return leftBracket;
	}

	@SuppressWarnings("unused")
	private void setLeftBracket(int leftBracket) {
		this.leftBracket = leftBracket;
	}
	
	public void setFormula(String calRule) {
		formula = replaceSubtration(calRule.trim());
		formula = "(" + formula + ")";
	}
	/*
	/*为了使公式中支持负数，使用“`”表示减号，使用“-”表示负号
	*/
	private String replaceSubtration(String vstr) {
		String tmp = "";
		String result = "";
		int startS = vstr.indexOf("-"); //
		if (startS != -1) {
			if (startS > 0) {
				tmp = vstr.substring(startS - 1, startS); //取出 “－” 号
				if (!"+".equals(tmp)
					&& !"-".equals(tmp)
					&& !"*".equals(tmp)
					&& !"/".equals(tmp)
					&& !"(".equals(tmp)) {
					//如果 不是 “＋ － × / （”
					result = result + vstr.substring(0, startS) + "`";
				} else
					result = result + vstr.substring(0, startS + 1);
			} else
				result = result + vstr.substring(0, startS + 1);
			vstr = vstr.substring(startS + 1);
		}
		while (startS != -1) {
			startS = vstr.indexOf("-");
			if (startS > 0) {
				tmp = vstr.substring(startS - 1, startS);
				if (!"+".equals(tmp)
					&& !"-".equals(tmp)
					&& !"*".equals(tmp)
					&& !"/".equals(tmp)
					&& !"(".equals(tmp))
					result = result + vstr.substring(0, startS) + "`";
				else
					result = result + vstr.substring(0, startS + 1);
			} else
				result = result + vstr.substring(0, startS + 1);
			vstr = vstr.substring(startS + 1);
		}
		result += vstr;

		return result;
	}

	public String getFormula() {

		return formula.replace('`', '-').substring(1, formula.length() - 1);
	}

	private int getRightBracket(String calRule) {
		rightBracket = 0;
		startR = calRule.indexOf(")");
		if (startR != -1) {
			calRule = calRule.substring(startR + 1, calRule.length());
		}
		while (startR != -1) {
			rightBracket++;
			startR = calRule.indexOf(")");
			calRule = calRule.substring(startR + 1, calRule.length());
		}
		return rightBracket;
	}

	@SuppressWarnings("unused")
	private void setRightBracket(int rightBracket) {
		this.rightBracket = rightBracket;
	}

	/*
	/*对比左右括号个数
	*/
	private boolean compareToLR() {
		int lb = getLeftBracket(formula);
		int rb = getRightBracket(formula);
		boolean CTLR = false;
		if (lb == rb) {
			Msg = "";
			CTLR = true;
		} else if (lb > rb) {
			Msg = "左括弧的个数多于右括弧，请检查！";
			msgindex = 1;
			CTLR = false;
		} else {
			Msg = "左括弧的个数少于右括弧，请检查！";
			msgindex = 2;
			CTLR = false;
		}
		return CTLR;
	}
	
	public String getCheckResult() {
		String msg = "ok";
		getResult();
		if (getMsgindex() > 0) {
			msg = Msg;
		}
		return msg;
	}
	/*
	/*检查公式中是否存在非法字符如(+、-)等
	*/
	private boolean checkFormula() {
		boolean isOk = true;
		String[] bracket = new String[2];
		String[] sign = new String[4];
		bracket[0] = "(";
		bracket[1] = ")";
		sign[0] = "+";
		sign[1] = "`";
		sign[2] = "*";
		sign[3] = "/";
		String vstr = "";
		for (int i = 0; i < bracket.length; i++) {
			for (int j = 0; j < sign.length; j++) {
				if (i == 0)
					vstr = bracket[i] + sign[j];
				else
					vstr = sign[j] + bracket[i];
				if (formula.indexOf(vstr) > 0) {
					Msg = "公式中存在非法字符" + vstr;
					msgindex = 3;
					isOk = false;
					return isOk;
				}
			}
		}
		for (int i = 0; i < sign.length; i++) {
			for (int j = 0; j < sign.length; j++) {
				vstr = sign[i] + sign[j];
				if (formula.indexOf(vstr) > 0) {
					Msg = "公式中存在非法字符" + vstr;
					msgindex = 3;
					isOk = false;
					return isOk;
				}
			}
		}
		if (formula.indexOf("()") > 0) {
			Msg = "公式中存在非法字符()";
			msgindex = 3;
			isOk = false;
		}
		return isOk;
	}
	public boolean checkValid() {
		if ((formula == null) || (formula.trim().length() <= 0)) {
			Msg = "请设置属性calRule!";
			msgindex = 4;
			return false;
		}
		return (compareToLR() && checkFormula());
	}

	/*
	/*返回公式执行结果
	 return double
	*/
	public BigDecimal getResult() {
		String formulaStr = "", calRule = "";
		BigDecimal value = new BigDecimal(0.0);
		calRule = this.formula;
		if (checkValid()) {
			for (int i = 0; i < leftBracket; i++) {
				int iStart = calRule.lastIndexOf("(") + 1;
				formulaStr =
					calRule
						.substring(
							iStart,
							iStart + calRule.substring(iStart).indexOf(")"))
						.trim();
				symbolParse(formulaStr);
				value = parseString();
				iStart = calRule.lastIndexOf("(");
				int iEnd = calRule.substring(iStart).indexOf(")") + 1;
				calRule =
					calRule.substring(0, iStart).trim()
						+ value
						+ calRule
							.substring(iStart + iEnd, calRule.length())
							.trim();
			}
		}
		double tmp = Math.pow(10, 3);
		value = new BigDecimal(Math.round(value.doubleValue() * tmp) / tmp);
		return value;
	}
	public void FormulaStr(String calRule) {
		String formulaStr = "";
		if (checkValid()) {
			for (int i = 0; i < leftBracket; i++) {
				formulaStr =
					calRule
						.substring(
							calRule.lastIndexOf("(") + 1,
							calRule.indexOf(")"))
						.trim();
				symbolParse(formulaStr);
				BigDecimal value = parseString();
				strValue = String.valueOf(value);
				//formulaVal = Double.parseDouble(formulaStr);
				calRule =
					calRule.substring(0, calRule.lastIndexOf("(")).trim()
						+ value
						+ calRule
							.substring(
								calRule.indexOf(")") + 1,
								calRule.length())
							.trim();
			}
		}
	}

	/*
	/*抽取最终括号内数据到List
	*/
	@SuppressWarnings("unchecked")
	private void symbolParse(String str) {
		list.clear();
		for (int i = 0; i < 4; i++) {
			compareMin(str);
			while (sym[i] != -1) {
				String insStr = str.substring(0, sym[i]).trim();
				list.add(insStr);
				insStr = str.substring(sym[i], sym[i] + 1).trim();
				list.add(insStr);
				str = str.substring(sym[i] + 1, str.length()).trim();
				compareMin(str);
			}
		}
		if (sym[0] == -1 && sym[1] == -1 && sym[2] == -1 & sym[3] == -1) {
			list.add(str);
		}
	}
	/*
	/*循环比较赋SubString起始值
	*/
	private void compareMin(String str) {
		int sps = str.indexOf("`"); //减法subtration
		sym[0] = sps;
		int spa = str.indexOf("+"); //加法addition
		sym[1] = spa;
		int spd = str.indexOf("/"); //除法division
		sym[2] = spd;
		int spm = str.indexOf("*"); //乘法multiplication
		sym[3] = spm;
		for (int i = 1; i < sym.length; i++) {
			for (int j = 0; j < sym.length - i; j++)
				if (sym[j] > sym[j + 1]) {
					int temp = sym[j];
					sym[j] = sym[j + 1];
					sym[j + 1] = temp;
				}
		}
	}

	@SuppressWarnings("unused")
	private BigDecimal parseString()
		throws NumberFormatException, StringIndexOutOfBoundsException {
		try {
			calculate();

			String resu = "" + answer;

			return answer;
		} catch (Exception e) {
			String resu = "" + answer;

			Msg = "错误：" + e.getMessage();
			msgindex = 3;
			return new BigDecimal(0.0);
		}
	}

	@SuppressWarnings("unused")
	private boolean checkdiv(double a, double b) {
		try {

			return true;

		} catch (Exception e) {

			return false;
		}

	}

	@SuppressWarnings("unchecked")
	private void calculate() {
		/*
		/*处理除法
		*/
		int spd = list.indexOf("/");
		while (spd != -1) {
			leftNumber = list.get(spd - 1).toString();
			rightNumber = list.get(spd + 1).toString();
			list.remove(spd - 1);
			list.remove(spd - 1);
			list.remove(spd - 1);

			double ln = Double.valueOf(leftNumber).doubleValue();
			double rn = Double.valueOf(rightNumber).doubleValue();

			double answer = ln / rn;
			if (rn == 0) {
				answer = 0;
			}

			list.add(spd - 1, String.valueOf(answer));
			spd = list.indexOf("/");
		}

		/*
		/*处理乘法
		*/
		int spm = list.indexOf("*");
		while (spm != -1) {
			leftNumber = list.get(spm - 1).toString();
			rightNumber = list.get(spm + 1).toString();
			list.remove(spm - 1);
			list.remove(spm - 1);
			list.remove(spm - 1);
			double ln = Double.valueOf(leftNumber).doubleValue();
			double rn = Double.valueOf(rightNumber).doubleValue();
			double answer = ln * rn;
			list.add(spm - 1, String.valueOf(answer));
			spm = list.indexOf("*");

		}
		/*
		/*处理减法
		*/
		int sps = list.indexOf("`");
		while (sps != -1) {
			leftNumber = list.get(sps - 1).toString();
			rightNumber = list.get(sps + 1).toString();
			list.remove(sps - 1);
			list.remove(sps - 1);
			list.remove(sps - 1);
			double ln = Double.valueOf(leftNumber).doubleValue();
			double rn = Double.valueOf(rightNumber).doubleValue();
			double answer = ln - rn;

			list.add(sps - 1, String.valueOf(answer));
			sps = list.indexOf("`");
		}

		/*
		/*处理加法
		*/
		int spa = list.indexOf("+");
		while (spa != -1) {
			leftNumber = list.get(spa - 1).toString();
			rightNumber = list.get(spa + 1).toString();
			list.remove(spa - 1);
			list.remove(spa - 1);
			list.remove(spa - 1);
			double ln = Double.valueOf(leftNumber).doubleValue();
			double rn = Double.valueOf(rightNumber).doubleValue();

			double answer = ln + rn;
			list.add(spa - 1, String.valueOf(answer));
			spa = list.indexOf("+");

		}

		if (list.size() != 0) {
			String result = list.get(0).toString();
			if (result == null || result.length() == 0)
				result = "0";

			answer = new BigDecimal(list.get(0).toString());
		}

	}

}